#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include <cstdio>
#include <cstring>

std::string ToHex(pthread_t tid)
{
    char buffer[64];
    snprintf(buffer, 64, "0x%0lx", tid);
    return buffer;
}
class ThreadData
{
public:
    ThreadData()
    {
    }
    void Init(const std::string &name, int a, int b)
    {
        _name = name;
        _a = a;
        _b = b;
        // _tid = tid;
    }
    pthread_t ID() { return _tid; }
    void SetId(pthread_t tid) { _tid = tid; }
    void Execute()
    {
        _ret = _a + _b;
    }
    int Result()
    {
        return _ret;
    }
    int A() { return _a; }
    int B() { return _b; }
    std::string Name() { return _name; }
    ~ThreadData()
    {
    }

private:
    std::string _name;
    int _a;
    int _b;
    int _ret;
    pthread_t _tid;
};

int tid;
int *addr;
void *routine1(void *args)
{
    std::string name = static_cast<const char *>(args);
    int a = 100;
    addr = &a;
    while (true)
    {
        std::cout << "new thread name is: " << name << ", thread ID is : " << ToHex(pthread_self()) << std::endl;
        sleep(1);
        break;
    }
    // pthread_cancel(tid);
    // sleep(5);
    return (void *)10; // 返回值可以是变量，对象等等。
}
void *routine2(void *args)
{
    std::string name = static_cast<const char *>(args);
    while (true)
    {
        std::cout << "new thread name is: " << name << ", thread ID is : " << ToHex(pthread_self()) << ", 修改val: " << (*addr)++ << std::endl;
        sleep(1);
    }
    return (void *)10; // 返回值可以是变量，对象等等。
}

void *routine3(void *args)
{
    int(*a)[2] = static_cast<int(*)[2]>(args);
    for (int j = 0; j < 10; j++)
    {
        for (int i = 0; i < 2; i++)
        {
            a[j][i] = i * j;
        }
    }
    return (void *)a;
}

__thread int gval = 100; //__thread 让所有的进程都单独存一份当前变量

void *routine(void *args)
{
    while (true)
    {
        std::cout << "new thread " << "全局val: " << gval << ", 全局val的地址: " << &gval << std::endl;
        gval++;
        sleep(1);
    }
    return (void *)100;
}
int main()
{
    // pthread_t tid1;
    // pthread_t tid2;
    // pthread_create(&tid1, nullptr, routine1, (void *)"thread-1");
    // pthread_create(&tid2, nullptr, routine2, (void *)"thread-2");
    // tid = tid2;
    // int nums[10][2];
    // printf("nums: %p\n", nums);
    pthread_t tid;
    pthread_create(&tid, nullptr, routine, nullptr);
    // pthread_create(&tid, nullptr, routine3, (void *)nums);

    while (true)
    {
        std::cout << "main thread " << "全局val: " << gval << ", 全局val的地址: " << &gval << std::endl;
        sleep(1);
    }

    void *ret;
    pthread_join(tid, &ret);

    // sleep(1);

    // //如果把主线程取消了呢?
    // std::cout <<"取消主线程" << std::endl;
    // pthread_cancel(pthread_self());

    // pthread_join(tid, nullptr); // 默认阻塞等待，线程退出

    // pthread_cancel(tid); //PTHREAD_CANCELED//取消线程

    // sleep(5);
    // pthread_detach(tid); //一旦分离就不让等待了

    // pthread_join(tid1, nullptr); // 默认阻塞等待，线程退出
    // pthread_join(tid2, nullptr); //
    // void *ret1;
    // void *ret2;

    // pthread_join(tid, &ret2);
    // std::cout << "thread : " << ToHex(tid2) << " exit return: " << (long long)ret2 << std::endl;

    // pthread_join(tid, &ret1);

    // std::cout << "thread : " << ToHex(tid1) << " exit return: " << (long long)ret1 << std::endl;

    // 父进程要是退了，子进程也默认退了

    // void* ret;
    // int n = pthread_join(tid,&ret);
    // if (n != 0) //等待失败
    //     std::cout << n << " error: " << strerror(n) << std::endl;
    // std::cout << "thread : " << ToHex(tid) << " exit return: " << (long long)ret << std::endl;

    // 一个线程可以修改另一个线程的内容吗? -> 定义全局变量可以修改，所以线程共享栈空间。

    // pthread_t tid1;
    // pthread_t tid2;
    // pthread_create(&tid1, nullptr, routine1, (void *)"thread-1");
    // pthread_create(&tid2, nullptr, routine2, (void *)"thread-2");

    // while(true)
    // {
    //     std::cout << "i am main thread: " << ToHex(pthread_self()) << std::endl;
    //     sleep(1);
    // }
    return 0;
}

// void *routine(void *args)
// {
//     ThreadData *tb = static_cast<ThreadData *>(args);
//     while (true)
//     {
//         std::cout << "new thread name is: " << tb->Name() << "thread ID is : " << ToHex(pthread_self()) << std::endl;
//         sleep(1);
//         break;
//     }
//     tb->Execute();
//     return tb; // 返回值可以是变量，对象等等。
// }
// const int M = 10;

// int main()
// {
//     //如果子线程异常嗯?
//     // pthread_t tid1;
//     // pthread_t tid2;
//     // pthread_create(&tid1,nullptr,routine1,(void*)"thread-1");
//     // pthread_create(&tid2,nullptr,routine1,(void*)"thread-2");

//     // void* ret;
//     // int n = pthread_join(tid,&ret);
//     // if (n != 0) //等待失败
//     //     std::cout << n << " error: " << strerror(n) << std::endl;
//     // std::cout << "thread : " << ToHex(tid) << " exit return: " << (long long)ret << std::endl;

//     // //创建多个进程
//     // ThreadData t[M];
//     // //设置数据
//     // for (int i = 0; i < M; i++)
//     // {
//     //     char buff[64];
//     //     snprintf(buff,64,"new thread-%d",i);
//     //     t[i].Init(buff,i*10,i*20);
//     //     //线程的tid还没被创建呢，你设置有个啥用啊?
//     // }

//     // for (int i = 0; i < M; i++)
//     // {
//     //     pthread_t tid;
//     //     int n = pthread_create(&tid,nullptr,routine,(void*)(&t[i]));
//     //     if (n != 0)
//     //     {
//     //         printf("thread: %d is not create\n",i);
//     //     }
//     //     //在创建完线程之后再设置ID值。
//     //     t[i].SetId(tid);
//     //     sleep(1);
//     // }

//     // //等待线程
//     // for (int i = 0; i < M; i++)
//     // {
//     //     int n = pthread_join(t[i].ID(),nullptr);
//     //     if (n != 0)
//     //     {
//     //         std::cout << "等待 new thread: " << ToHex(t[i].ID()) << " error , info: " << strerror(n) << std::endl;
//     //         exit(1);
//     //     }
//     // }

//     // //对结果进行总和
//     // for (int i = 0; i < M; i++)
//     // {
//     //     printf("t[%d], thread id: %ld, %d+%d=%d\n",i,t[i].ID(),t[i].A(),t[i].B(),t[i].Result());

//     // }
//     // pthread_t tid;

//     // ThreadData* tb = new ThreadData;
//     // tb->Init("new thread-1",10,20);
//     // pthread_create(&tid, nullptr, routine, (void *)tb);

//     // void *ret;
//     // pthread_join(tid, &ret);
//     // std::cout << "i am main thread, thread id : " << ToHex(pthread_self()) << std::endl;
//     // std::cout << "new thread is : " << ToHex(tid) << ", exit result is: " << ((ThreadData*)tb)->Result() << std::endl;
//     // while(true)
//     // {
//     //     std::cout << "i am main thread, thread id : " << ToHex(pthread_self()) << std::endl;
//     //     sleep(1);
//     // }

//     return 0;
// }

// void *run(void *a)
// {
//     while (1)
//     {
//         // std::cout << static_cast<char*>(a) << "new thread, pid: " << getpid() <<  "cnt: " << cnt++<<std::endl;
//         std::cout << (char*)(a) << "new thread, pid: " << getpid() <<  "cnt: " << cnt++<<std::endl;
//         sleep(1);
//     }
// }

// int main()
// {
//     pthread_t id1;
//     pthread_t id2;
//     pthread_create(&id1, nullptr, run, (void *)"new thread1"); //进程创建

//     std::cout << "I am a process, pid: " << getpid() << std::endl;
//     while (1)
//     {
//         std::cout << "main thread , pid: " << getpid() << " cnt: " << cnt++ << std::endl;
//         sleep(1);
//     }

//     return 0;
// }